//----------------------------------------------------------------------------------------------
//	Filename:	FeatureDescriptorStructureGraph.cpp
//	Author:		Sandro Spina
//	Date:		23/07/2013
//----------------------------------------------------------------------------------------------
//----------------------------------------------------------------------------------------------

#include "FeatureDescStructureGraph.h"
#include "PointCloudSegmentation.h"
#include "Scene/Environment.h"

#include <boost\interprocess\file_mapping.hpp>
#include <boost\interprocess\mapped_region.hpp>
#include <boost\filesystem\operations.hpp>
#include <boost\filesystem\path.hpp>
#include <boost\filesystem.hpp>

#include <boost\lexical_cast.hpp>

FeatureDescStructureGraph::FeatureDescStructureGraph(int p_initialNodeId, PointCloudSegmentation * p_pcs) //Environment * p_environment)
{			
	nodes = new std::map<int, Node*>();
	m_stringDescriptors = new std::map<int, std::vector<std::vector<int>>*>();
	m_pcs = p_pcs;	
	AddNode(p_initialNodeId);
	initial_node_id = p_initialNodeId;
}

int FeatureDescStructureGraph::GetInitialNodeId()
{
	return initial_node_id;
}

FeatureDescStructureGraph::Node * FeatureDescStructureGraph::GetInitialNode()
{
	return nodes->at(initial_node_id);
}

//Create and populate a new node to represent a surface segment. Add to nodes map.
void FeatureDescStructureGraph::AddNode(FeatureDescStructureGraph::Node * p_node)
{
	(*nodes)[p_node->id] = p_node;
}	

FeatureDescStructureGraph::Node * FeatureDescStructureGraph::AddNode(int p_nodeId)
{
	std::map<int, Node*>::iterator n_it = nodes->find(p_nodeId);
	if (n_it != nodes->end()) return n_it->second;
	FeatureDescStructureGraph::Node * n = new Node();
	n->edges = new std::map<int, EdgeStats*>();
	n->id = p_nodeId;
	n->distances_over_under = std::pair<float,float>(0,0);
	(*nodes)[p_nodeId] = n;
	return n;
}

FeatureDescStructureGraph::Node * FeatureDescStructureGraph::AddNode(StructureGraph::Node * p_node)
{
	std::map<int, Node*>::iterator n_it = nodes->find(p_node->id);
	if (n_it != nodes->end()) return n_it->second;
	FeatureDescStructureGraph::Node * n = new Node();	
	n->edges = new std::map<int, EdgeStats*>();
	n->id = p_node->id;
	n->distances_over_under = std::pair<float,float>(0,0);
	CopyProperties(n, p_node);
	(*nodes)[n->id] = n;
	return n;
}

bool FeatureDescStructureGraph::ContainsNode(int pId)
{
	if (nodes->find(pId) != nodes->end()) return true;
	return false;
}

FeatureDescStructureGraph::Node * FeatureDescStructureGraph::GetNode(int _id)
{
	return nodes->at(_id);
}

void FeatureDescStructureGraph::CopyProperties(Node * _n, StructureGraph::Node * str_node)
{
	SegmentsGraph::SurfaceSegment * ss = str_node->segment;
	_n->obb			=	ss->obb;
	_n->orientation	=	ss->orientation;
	_n->point_count	=	ss->points->size();
	_n->shape		=	ss->shape_primitive;
	_n->coverage	=	ss->coverage;
}

void FeatureDescStructureGraph::AddConnection(Node * src_node, Node * sink_node, StructureGraph::EdgeStats* _stats)
{
	EdgeStats * e_stats = new EdgeStats();
	e_stats->direct = 1.0f;
	e_stats->disconnected = false;
	e_stats->dot = _stats->dot;
	e_stats->epsilon = _stats->epsilon;
	(*src_node->edges)[sink_node->id] = e_stats;
}

void FeatureDescStructureGraph::ComputeVoxelGrids(float p_voxel_length, std::vector<CloudPoint> &p_pointList)
{	
	std::cout << "Computing Voxel Grids for " << initial_node_id << " ... ";
	m_grid_u_v_w				= ComputeVoxelGrid(p_voxel_length, p_pointList, false, false, false);
	m_grid_u_v_inv_w			= ComputeVoxelGrid(p_voxel_length, p_pointList, false, true, false);
	m_grid_u_v_w_inv			= ComputeVoxelGrid(p_voxel_length, p_pointList, false, false, true);
	m_grid_u_v_inv_w_inv		= ComputeVoxelGrid(p_voxel_length, p_pointList, false, true, true);
	
	m_grid_u_inv_v_w			= ComputeVoxelGrid(p_voxel_length, p_pointList, true, false, false);
	m_grid_u_inv_v_inv_w		= ComputeVoxelGrid(p_voxel_length, p_pointList, true, true, false);
	m_grid_u_inv_v_w_inv		= ComputeVoxelGrid(p_voxel_length, p_pointList, true, false, true);
	m_grid_u_inv_v_inv_w_inv	= ComputeVoxelGrid(p_voxel_length, p_pointList, true, true, true);	
	std::cout << " done." << std::endl;
}

FeatureDescStructureGraph::VoxelGrid * FeatureDescStructureGraph::ComputeVoxelGrid(float p_voxel_length, std::vector<CloudPoint> &p_pointList, bool _inverse_u, bool _inverse_v, bool _inverse_w)
{
	VoxelGrid * m_grid = new VoxelGrid(p_voxel_length, this);
	Node * p_node = nodes->at(initial_node_id);
	m_grid->uvw.U = p_node->obb.obb_0;
	if (_inverse_u) m_grid->uvw.U *= -1;
	m_grid->uvw.V = p_node->obb.obb_1;
	if (_inverse_v) m_grid->uvw.V *= -1;
	m_grid->uvw.W = p_node->obb.obb_2;
	if (_inverse_w) m_grid->uvw.W *= -1;

	m_grid->m_inverse_u = _inverse_u;

	m_grid->o_model_xyz =	(p_node->obb.p_0_min.Distance + ((p_node->obb.p_0_max.Distance - p_node->obb.p_0_min.Distance) /2)) * (p_node->obb.obb_0) +
							(p_node->obb.p_1_min.Distance + ((p_node->obb.p_1_max.Distance - p_node->obb.p_1_min.Distance) /2)) * (p_node->obb.obb_1) +
							(p_node->obb.p_2_min.Distance + ((p_node->obb.p_2_max.Distance - p_node->obb.p_2_min.Distance) /2)) * (p_node->obb.obb_2);	
	
	float min_u =  100000.f;
	float min_v =  100000.f;
	float min_w =  100000.f;

	float max_u = -100000.f;
	float max_v = -100000.f;
	float max_w = -100000.f;

	CloudPoint p = CloudPoint(0,0,0);

	float d_u; float d_v; float d_w; Vector3 corner;

	std::vector<Vector3> obb_corners = p_node->obb.GetOBBCorners();
	for (auto corners : obb_corners)
	{		
		d_u = (corners - (m_grid->o_model_xyz)).Dot(m_grid->uvw.U);
		d_v = (corners - (m_grid->o_model_xyz)).Dot(m_grid->uvw.V); 
		d_w = (corners - (m_grid->o_model_xyz)).Dot(m_grid->uvw.W); 
		if (d_u > max_u) max_u = d_u; if (d_u < min_u) min_u = d_u;
		if (d_v > max_v) max_v = d_v; if (d_v < min_v) min_v = d_v;
		if (d_w > max_w) max_w = d_w; if (d_w < min_w) min_w = d_w;
	}

	m_grid->min_obb_uvw = Vector3(min_u, min_v, min_w);
	m_grid->max_obb_uvw = Vector3(max_u, max_v, max_w);

	min_u = 100000.f; min_v = 100000.f; min_w = 100000.f;
	max_u = -100000.f; max_v = -100000.f; max_w = -100000.f;

	for (auto surface_it = m_pcs->m_segmentsGraph->m_surfaceSegments->begin(); surface_it != m_pcs->m_segmentsGraph->m_surfaceSegments->end(); surface_it++)
	{
		for (auto points_in_surface_it = surface_it->second->points->begin(); points_in_surface_it != surface_it->second->points->end(); points_in_surface_it++)
		{
			p = p_pointList.at(*points_in_surface_it);
			d_u = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.U);
			d_v = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.V); 
			d_w = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.W); 
			if (d_u > max_u) max_u = d_u; if (d_u < min_u) min_u = d_u;
			if (d_v > max_v) max_v = d_v; if (d_v < min_v) min_v = d_v;
			if (d_w > max_w) max_w = d_w; if (d_w < min_w) min_w = d_w;
		}		
	}
					
	for (auto edge_it = m_pcs->m_segmentsGraph->m_edgeSegments->begin(); edge_it != m_pcs->m_segmentsGraph->m_edgeSegments->end(); edge_it++)
	{
		for (auto points_in_edge_it = edge_it->second->points->begin(); points_in_edge_it != edge_it->second->points->end(); points_in_edge_it++)
		{
			p = p_pointList.at(*points_in_edge_it);
			d_u = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.U);
			d_v = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.V); 
			d_w = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.W);
			if (d_u > max_u) max_u = d_u; if (d_u < min_u) min_u = d_u;
			if (d_v > max_v) max_v = d_v; if (d_v < min_v) min_v = d_v;
			if (d_w > max_w) max_w = d_w; if (d_w < min_w) min_w = d_w;
		}
	}

	m_grid->min_model_uvw = Vector3(min_u, min_v, min_w);
	m_grid->max_model_uvw = Vector3(max_u, max_v, max_w);
	
	m_grid->min_model_uvw_br.X = m_grid->min_model_uvw.X;
	m_grid->min_model_uvw_br.Y = m_grid->min_model_uvw.Y;
	m_grid->min_model_uvw_br.Z = m_grid->min_model_uvw.Z;
	
	int cell_count_u = 0; int cell_count_v = 0; int cell_count_w = 0;
	if ((m_grid->max_model_uvw.X - m_grid->min_model_uvw.X) < p_voxel_length) cell_count_u = 1; else cell_count_u = (int) ((m_grid->max_model_uvw.X - m_grid->min_model_uvw.X) / p_voxel_length) +1;
	if ((m_grid->max_model_uvw.Y - m_grid->min_model_uvw.Y) < p_voxel_length) cell_count_v = 1; else cell_count_v = (int) ((m_grid->max_model_uvw.Y - m_grid->min_model_uvw.Y) / p_voxel_length) +1;
	if ((m_grid->max_model_uvw.Z - m_grid->min_model_uvw.Z) < p_voxel_length) cell_count_w = 1; else cell_count_w = (int) ((m_grid->max_model_uvw.Z - m_grid->min_model_uvw.Z) / p_voxel_length) +1;
	
	m_grid->u_cells_count = cell_count_u;
	m_grid->v_cells_count = cell_count_v;
	m_grid->w_cells_count = cell_count_w;

	//Compute the location of the central cell	
	m_grid->o_grid_u = Maths::Floor(Maths::Abs(m_grid->min_model_uvw.X / p_voxel_length));
	m_grid->o_grid_v = Maths::Floor(Maths::Abs(m_grid->min_model_uvw.Y / p_voxel_length));
	m_grid->o_grid_w = Maths::Floor(Maths::Abs(m_grid->min_model_uvw.Z / p_voxel_length));

	//std::cout << "Original:: o_grid_u " << m_grid->min_model_uvw.X / p_voxel_length << " o_grid_v " << m_grid->min_model_uvw.Y / p_voxel_length << " o_grid_w " << m_grid->min_model_uvw.W / p_voxel_length << std::endl;	
	
	//float dst_to_cell_centroid = Maths::Frac(m_grid->min_model_uvw.X / p_voxel_length);	
	//float shift_dst = dst_to_cell_centroid - 0.5f; 
	//if (dst_to_cell_centroid < 0.5f)  shift_dst = 1 - shift_dst;
	float floor = Maths::Floor(m_grid->min_model_uvw.X / p_voxel_length);
	float frac = Maths::Frac(Maths::Abs(m_grid->min_model_uvw.X / p_voxel_length));
	float shift_dst = m_grid->min_model_uvw.X / p_voxel_length;
	if (frac > 0.5) shift_dst = floor - 0.5f; else shift_dst = (floor+1) - 0.5f;
	//std::cout << floor << " " << frac << " " << shift_dst << std::endl;
	
	m_grid->min_model_uvw.X= shift_dst; m_grid->u_cells_count++;
	m_grid->o_grid_u = Maths::Floor(Maths::Abs(m_grid->min_model_uvw.X / p_voxel_length));
	m_grid->min_model_uvw_br.X = m_grid->min_model_uvw.X;

	//std::cout << "Updated:: o_grid_u " << m_grid->min_model_uvw.X / p_voxel_length << " o_grid_v " << m_grid->min_model_uvw.Y / p_voxel_length << " o_grid_w " << m_grid->min_model_uvw.W / p_voxel_length << std::endl;	

	//Fill up the voxel grid
	bool onOrigin = false;

	for (auto surface_it = m_pcs->m_segmentsGraph->m_surfaceSegments->begin(); surface_it != m_pcs->m_segmentsGraph->m_surfaceSegments->end(); surface_it++)
	{
		if (surface_it->second->id == initial_node_id) onOrigin = true;
		for (auto points_in_surface_it = surface_it->second->points->begin(); points_in_surface_it != surface_it->second->points->end(); points_in_surface_it++)
		{
			p = p_pointList.at(*points_in_surface_it);
			d_u = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.U);
			d_v = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.V);
			d_w = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.W);			
			m_grid->IncVoxelSurfaceCount(Maths::Floor((d_u - m_grid->min_model_uvw.X) / p_voxel_length), Maths::Floor((d_v - m_grid->min_model_uvw.Y) / p_voxel_length), Maths::Floor((d_w - m_grid->min_model_uvw.Z) / p_voxel_length), onOrigin, surface_it->second->id);
		}
		onOrigin = false;
	}
	
	for (auto edge_it = m_pcs->m_segmentsGraph->m_edgeSegments->begin(); edge_it != m_pcs->m_segmentsGraph->m_edgeSegments->end(); edge_it++)
	{
		for (auto points_in_edge_it = edge_it->second->points->begin(); points_in_edge_it != edge_it->second->points->end(); points_in_edge_it++)
		{
			p = p_pointList.at(*points_in_edge_it);
			d_u = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.U);
			d_v = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.V);
			d_w = (p.m_vertex.Position - (m_grid->o_model_xyz)).Dot(m_grid->uvw.W);
			m_grid->IncVoxelEdgeCount(Maths::Floor((d_u - m_grid->min_model_uvw.X) / p_voxel_length), Maths::Floor((d_v - m_grid->min_model_uvw.Y) / p_voxel_length), Maths::Floor((d_w - m_grid->min_model_uvw.Z) / p_voxel_length), false);
		}
	}

	/*std::cout << "Segment: " << p_node->id << ", UVW:" << m_grid->uvw.ToString() << std::endl;
	std::cout << "Grid Cell Count: U" << cell_count_u << " V:" << cell_count_v << " W:" << cell_count_w << std::endl;
	std::cout << "Min Model UVW: " << m_grid->min_model_uvw.ToString() << std::endl;
	std::cout << "Max Model UVW: " << m_grid->max_model_uvw.ToString() << std::endl;
	std::cout << "Min SegOBB UVW: " << m_grid->min_obb_uvw.ToString() << std::endl;
	std::cout << "Max SegOBB UVW: " << m_grid->max_obb_uvw.ToString() << std::endl;
	std::cout << "Model Origin XYZ:: " << m_grid->o_model_xyz.ToString() << std::endl;
	std::cout << "Origin XYZ:: " << m_grid->o_model_xyz.ToString() << std::endl;	
	std::cout << "Grid Origin UVW:: " << Vector3(m_grid->o_grid_u, m_grid->o_grid_v, m_grid->o_grid_w).ToString() << std::endl;
	std::cout << "Number of Cells in Grid = " << m_grid->m_voxels->size() << std::endl;
	*/
	return m_grid;
}

void FeatureDescStructureGraph::ComputeStringDescriptors(int _max_length)
{
	//Incrementally compute stringDescriptors "nodeId-nodeId-nodeId-..."
	//Compute from string length == 2 to _max_length
	m_stringDescriptors->clear();	
	std::vector<std::vector<int>> nxt_descriptors;
	std::vector<int> init; init.push_back(initial_node_id);
	
	(*m_stringDescriptors)[1] = new std::vector<std::vector<int>>();
	(*m_stringDescriptors)[1]->push_back(init);
		
	bool loop = false;
	for (int i=2; i<=_max_length; i++)
	{
		(*m_stringDescriptors)[i] = new std::vector<std::vector<int>>();
		//compute new descriptors from those with length == i-1		
		for (std::vector<std::vector<int>>::iterator desc_it = (*m_stringDescriptors)[i-1]->begin(); desc_it != (*m_stringDescriptors)[i-1]->end(); desc_it++)
		{
			//Move till end end of the current descriptor ... 
			std::vector<int> desc_prefix;
			int last_node_id = desc_it->at(desc_it->size()-1);
			Node * last_node = nodes->at(last_node_id);
			for (std::map<int, EdgeStats*>::iterator edge_it = last_node->edges->begin(); edge_it != last_node->edges->end(); edge_it++)
			{
				std::vector<int> new_desc;
				loop=false;
				for (std::vector<int>::iterator crt_desc_it = desc_it->begin(); crt_desc_it != desc_it->end(); crt_desc_it++) 
				{
					if (*crt_desc_it == edge_it->first) { loop = true; break; }
					new_desc.push_back(*crt_desc_it);
				}
				if (loop) continue;
				new_desc.push_back(edge_it->first);
				(*m_stringDescriptors)[i]->push_back(new_desc);
				nxt_descriptors.push_back(new_desc);
			}
		}
	}

	PrintDescriptors();
}

//Strings of node ids from the initial state of this feature descriptor structure graph.
std::vector<std::vector<int>> * FeatureDescStructureGraph::GetStringDescriptors(int _length) 
{	
	return (*m_stringDescriptors)[_length];
}

std::pair <float, std::vector<int>> FeatureDescStructureGraph::GetStringDescriptorMaxCoverage(int _length)
{
	std::vector<std::vector<int>> * descriptors = (*m_stringDescriptors)[_length];
	std::vector<int> maxDesc;
	float currentMaxScore = 0;	
	float currentScore;

	for (std::vector<std::vector<int>>::iterator all_desc_it = descriptors->begin(); all_desc_it != descriptors->end(); all_desc_it++)
	{	
		currentScore = 0;
		for (std::vector<int>::iterator desc_it = all_desc_it->begin(); desc_it != all_desc_it->end(); desc_it++)
		{
			//std::cout << "Coverage Node " << *desc_it << " = " << nodes->at(*desc_it)->coverage << std::endl;
			currentScore += nodes->at(*desc_it)->coverage;
		}
		//std::cout << "Score = " << currentScore << std::endl;
		if (currentScore > currentMaxScore) 
		{
			maxDesc.clear();
			for (std::vector<int>::iterator desc_it = all_desc_it->begin(); desc_it != all_desc_it->end(); desc_it++) maxDesc.push_back(*desc_it);
			currentMaxScore = currentScore;			
		}		
	}
	return std::pair<float, std::vector<int>>(currentMaxScore, maxDesc);
}

std::pair <float, std::vector<int>> FeatureDescStructureGraph::GetStringDescriptorMaxPointCount(int _length)
{
	std::vector<std::vector<int>> * descriptors = (*m_stringDescriptors)[_length];
	std::vector<int> maxDesc;
	float currentMaxScore = 0;	
	float currentScore;

	for (std::vector<std::vector<int>>::iterator all_desc_it = descriptors->begin(); all_desc_it != descriptors->end(); all_desc_it++)
	{	
		currentScore = 0;
		for (std::vector<int>::iterator desc_it = all_desc_it->begin(); desc_it != all_desc_it->end(); desc_it++)
		{
			currentScore += nodes->at(*desc_it)->point_count;
		}
		if (currentScore > currentMaxScore) 
		{
			maxDesc.clear();
			for (std::vector<int>::iterator desc_it = all_desc_it->begin(); desc_it != all_desc_it->end(); desc_it++) maxDesc.push_back(*desc_it);
			currentMaxScore = currentScore;
		}
	}
	return std::pair<float, std::vector<int>>(currentMaxScore, maxDesc);
}

std::pair <float, std::vector<int>> FeatureDescStructureGraph::GetStringDescriptorMaxCoverageCrossPointCount(int _length)
{
	std::vector<std::vector<int>> * descriptors = (*m_stringDescriptors)[_length];
	std::vector<int> maxDesc;
	float currentMaxScore = 0;	
	float currentScore;

	for (std::vector<std::vector<int>>::iterator all_desc_it = descriptors->begin(); all_desc_it != descriptors->end(); all_desc_it++)
	{	
		currentScore = 0;
		for (std::vector<int>::iterator desc_it = all_desc_it->begin(); desc_it != all_desc_it->end(); desc_it++)
		{
			currentScore += (nodes->at(*desc_it)->coverage * nodes->at(*desc_it)->point_count);
		}
		if (currentScore > currentMaxScore) 
		{
			maxDesc.clear();
			for (std::vector<int>::iterator desc_it = all_desc_it->begin(); desc_it != all_desc_it->end(); desc_it++) maxDesc.push_back(*desc_it);
			currentMaxScore = currentScore;
		}
	}
	return std::pair<float, std::vector<int>>(currentMaxScore, maxDesc);
}

void FeatureDescStructureGraph::WriteToBFDSGFile(std::string _filepath)
{
	std::string pcsPath = _filepath+".bfdsg";		
	const char * filename = pcsPath.c_str();	
	
	int numberOfNodes = nodes->size();
	//Determine size of file first
	int sizeNodes = 0;
	for (auto n : *nodes) sizeNodes+=n.second->sizeInBytes();	
	
	int numberOfGrids = 8;
	int sizeGrids = 0;
	sizeGrids += m_grid_u_v_w->sizeInBytes();
	sizeGrids += m_grid_u_v_inv_w->sizeInBytes();
	sizeGrids += m_grid_u_v_w_inv->sizeInBytes();
	sizeGrids += m_grid_u_v_inv_w_inv->sizeInBytes();
	sizeGrids += m_grid_u_inv_v_w->sizeInBytes();
	sizeGrids += m_grid_u_inv_v_inv_w->sizeInBytes();
	sizeGrids += m_grid_u_inv_v_w_inv->sizeInBytes();
	sizeGrids += m_grid_u_inv_v_inv_w_inv->sizeInBytes();

	int numberOfStringDescriptors = m_stringDescriptors->size();
	int sizeStringDescriptors = 0;

	//std::map<int, std::vector<std::vector<int>>*>	
	sizeStringDescriptors += sizeof(int);       //size of map first
	for (auto sd : *m_stringDescriptors) {
		sizeStringDescriptors += sizeof(int);   //descriptor size in vectors
		sizeStringDescriptors += sizeof(int);   //number of descriptors with this size
		for (auto de : *(sd.second))
		{
			int descSize = de.size();
			sizeStringDescriptors += sizeof(int); //size of this descriptor
			sizeStringDescriptors += sizeof(int) * descSize;
		}
	}

	size_t file_size = sizeof(int) + sizeNodes + 
						sizeof(int) + sizeGrids + 
						sizeof(int) + sizeStringDescriptors;
	
	std::filebuf fbuf;
	fbuf.open(filename, std::ios_base::in | std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);	
	fbuf.pubseekoff( file_size - sizeof(char), std::ios_base::beg);
	fbuf.sputc(0);
	fbuf.close();

	size_t crtSize = 0;

	boost::interprocess::file_mapping m_file(filename, boost::interprocess::read_write);
	boost::interprocess::mapped_region region(m_file, boost::interprocess::read_write);						    

	int sizeint = sizeof(int);
	int sizefloat = sizeof(float);

	int * r_addr_i = (int*)region.get_address();			
	float * r_addr_f;
	size_t r_size = region.get_size();				
	std::cout << "[FeatureDescStrGraph         ] Writing Bin File " << pcsPath << ". AllocSize= [" << r_size << "] " << std::endl;

	*r_addr_i = numberOfNodes; r_addr_i++;	
	for (nodesIterator = nodes->begin(); nodesIterator != nodes->end(); nodesIterator++) 
	{							
		*r_addr_i = nodesIterator->second->id; r_addr_i++;
		*r_addr_i = nodesIterator->second->used; r_addr_i++;
		r_addr_f = (float*) r_addr_i;
		*r_addr_f = nodesIterator->second->coverage; r_addr_f++;
		*r_addr_f = nodesIterator->second->distances_over_under.first; r_addr_f++;
		*r_addr_f = nodesIterator->second->distances_over_under.first; r_addr_f++;
		r_addr_i = (int*) r_addr_f;
		*r_addr_i = nodesIterator->second->point_count; r_addr_i++;
		*r_addr_i = nodesIterator->second->shape; r_addr_i++;
		r_addr_f = (float*) r_addr_i;
		*r_addr_f = nodesIterator->second->orientation.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->orientation.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->orientation.Z; r_addr_f++;
		
		*r_addr_f = nodesIterator->second->obb.obb_0.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.obb_0.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.obb_0.Z; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.obb_1.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.obb_1.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.obb_1.Z; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.obb_2.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.obb_2.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.obb_2.Z; r_addr_f++;

		*r_addr_f = nodesIterator->second->obb.p_0_min.Normal.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_0_min.Normal.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_0_min.Normal.Z; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_0_min.Distance; r_addr_f++;

		*r_addr_f = nodesIterator->second->obb.p_0_max.Normal.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_0_max.Normal.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_0_max.Normal.Z; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_0_max.Distance; r_addr_f++;

		*r_addr_f = nodesIterator->second->obb.p_1_min.Normal.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_1_min.Normal.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_1_min.Normal.Z; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_1_min.Distance; r_addr_f++;

		*r_addr_f = nodesIterator->second->obb.p_1_max.Normal.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_1_max.Normal.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_1_max.Normal.Z; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_1_max.Distance; r_addr_f++;

		*r_addr_f = nodesIterator->second->obb.p_2_min.Normal.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_2_min.Normal.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_2_min.Normal.Z; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_2_min.Distance; r_addr_f++;

		*r_addr_f = nodesIterator->second->obb.p_2_max.Normal.X; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_2_max.Normal.Y; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_2_max.Normal.Z; r_addr_f++;
		*r_addr_f = nodesIterator->second->obb.p_2_max.Distance; r_addr_f++;
	
		*r_addr_f = nodesIterator->second->obb.buffer; r_addr_f++;
		
		r_addr_i = (int*) r_addr_f;
		*r_addr_i = nodesIterator->second->edges->size(); r_addr_i++;

		for (auto edg : *(nodesIterator->second->edges))
		{			
			*r_addr_i = edg.first; r_addr_i++;
			*r_addr_i = edg.second->strength; r_addr_i++;
			r_addr_f = (float*) r_addr_i;
			*r_addr_f = edg.second->epsilon; r_addr_f++;
			*r_addr_f = edg.second->direct; r_addr_f++;
			*r_addr_f = edg.second->occluded; r_addr_f++;
			r_addr_i = (int*) r_addr_f;
			edg.second->disconnected ? *r_addr_i = 0 : *r_addr_i = 1; r_addr_i++;
			*r_addr_i = edg.second->actions.size(); r_addr_i++;
			for (auto act : edg.second->actions)
			{
				*r_addr_i = act; r_addr_i++;
			}
		}			
	} //all nodes should be written now

	//Start persisting grids.
	*r_addr_i = numberOfGrids; r_addr_i++;
	
	*r_addr_i = m_grid_u_v_w->u_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_w->v_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_w->w_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_w->points_total; r_addr_i++;
	*r_addr_i = m_grid_u_v_w->o_grid_u; r_addr_i++;
	*r_addr_i = m_grid_u_v_w->o_grid_v; r_addr_i++;
	*r_addr_i = m_grid_u_v_w->o_grid_w; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	*r_addr_f = m_grid_u_v_w->grid_cell_spacing_u; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->grid_cell_spacing_v; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->grid_cell_spacing_w; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.U.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.U.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.U.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.V.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.V.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.V.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.W.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.W.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->uvw.W.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->o_model_xyz.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->o_model_xyz.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->o_model_xyz.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->max_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->max_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->max_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->max_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->max_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->max_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_model_uvw_br.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_model_uvw_br.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->min_model_uvw_br.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->scale.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->scale.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->scale.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w->rotation; r_addr_f++;					
	
	r_addr_i = (int*) r_addr_f;
	
	*r_addr_i = m_grid_u_v_w->m_voxels->size(); r_addr_i++;
	int x,y,z;
	for (auto v : *(m_grid_u_v_w->m_voxels))
	{
		x = VoxelGrid::GetXFromKey(v.first);
		y = VoxelGrid::GetYFromKey(v.first);
		z = VoxelGrid::GetZFromKey(v.first);
		*r_addr_i = x; r_addr_i++;
		*r_addr_i = y; r_addr_i++;
		*r_addr_i = z; r_addr_i++;
		*r_addr_i = v.second.surface_points_count; r_addr_i++;
		*r_addr_i = v.second.edge_points_count; r_addr_i++;
		v.second.inOrigin ? *r_addr_i = 1 : *r_addr_i = 0; r_addr_i++;
	}

	*r_addr_i = m_grid_u_v_inv_w->u_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w->v_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w->w_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w->points_total; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w->o_grid_u; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w->o_grid_v; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w->o_grid_w; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	*r_addr_f = m_grid_u_v_inv_w->grid_cell_spacing_u; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->grid_cell_spacing_v; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->grid_cell_spacing_w; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.U.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.U.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.U.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.V.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.V.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.V.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.W.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.W.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->uvw.W.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->o_model_xyz.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->o_model_xyz.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->o_model_xyz.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->max_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->max_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->max_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->max_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->max_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->max_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_model_uvw_br.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_model_uvw_br.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->min_model_uvw_br.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->scale.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->scale.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->scale.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w->rotation; r_addr_f++;					
	
	r_addr_i = (int*) r_addr_f;
		
	*r_addr_i = m_grid_u_v_inv_w->m_voxels->size(); r_addr_i++;	
	for (auto v : *(m_grid_u_v_inv_w->m_voxels)) 
	{
		x = VoxelGrid::GetXFromKey(v.first);
		y = VoxelGrid::GetYFromKey(v.first);
		z = VoxelGrid::GetZFromKey(v.first);
		*r_addr_i = x; r_addr_i++;
		*r_addr_i = y; r_addr_i++;
		*r_addr_i = z; r_addr_i++;
		*r_addr_i = v.second.surface_points_count; r_addr_i++;
		*r_addr_i = v.second.edge_points_count; r_addr_i++;
		v.second.inOrigin ? *r_addr_i = 1 : *r_addr_i = 0; r_addr_i++;		
	}

	*r_addr_i = m_grid_u_v_w_inv->u_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_w_inv->v_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_w_inv->w_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_w_inv->points_total; r_addr_i++;
	*r_addr_i = m_grid_u_v_w_inv->o_grid_u; r_addr_i++;
	*r_addr_i = m_grid_u_v_w_inv->o_grid_v; r_addr_i++;
	*r_addr_i = m_grid_u_v_w_inv->o_grid_w; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	*r_addr_f = m_grid_u_v_w_inv->grid_cell_spacing_u; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->grid_cell_spacing_v; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->grid_cell_spacing_w; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.U.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.U.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.U.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.V.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.V.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.V.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.W.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.W.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->uvw.W.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->o_model_xyz.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->o_model_xyz.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->o_model_xyz.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->max_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->max_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->max_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->max_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->max_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->max_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_model_uvw_br.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_model_uvw_br.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->min_model_uvw_br.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->scale.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->scale.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->scale.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_w_inv->rotation; r_addr_f++;					
	
	r_addr_i = (int*) r_addr_f;

	*r_addr_i = m_grid_u_v_w_inv->m_voxels->size(); r_addr_i++;	
	for (auto v : *(m_grid_u_v_w_inv->m_voxels)) 
	{
		x = VoxelGrid::GetXFromKey(v.first);
		y = VoxelGrid::GetYFromKey(v.first);
		z = VoxelGrid::GetZFromKey(v.first);
		*r_addr_i = x; r_addr_i++;
		*r_addr_i = y; r_addr_i++;
		*r_addr_i = z; r_addr_i++;
		*r_addr_i = v.second.surface_points_count; r_addr_i++;
		*r_addr_i = v.second.edge_points_count; r_addr_i++;
		v.second.inOrigin ? *r_addr_i = 1 : *r_addr_i = 0; r_addr_i++;		
	}
	
	*r_addr_i = m_grid_u_v_inv_w_inv->u_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w_inv->v_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w_inv->w_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w_inv->points_total; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w_inv->o_grid_u; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w_inv->o_grid_v; r_addr_i++;
	*r_addr_i = m_grid_u_v_inv_w_inv->o_grid_w; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	*r_addr_f = m_grid_u_v_inv_w_inv->grid_cell_spacing_u; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->grid_cell_spacing_v; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->grid_cell_spacing_w; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.U.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.U.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.U.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.V.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.V.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.V.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.W.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.W.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->uvw.W.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->o_model_xyz.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->o_model_xyz.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->o_model_xyz.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->max_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->max_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->max_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->max_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->max_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->max_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_model_uvw_br.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_model_uvw_br.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->min_model_uvw_br.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->scale.X; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->scale.Y; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->scale.Z; r_addr_f++;
	*r_addr_f = m_grid_u_v_inv_w_inv->rotation; r_addr_f++;					
	
	r_addr_i = (int*) r_addr_f;

	*r_addr_i = m_grid_u_v_inv_w_inv->m_voxels->size(); r_addr_i++;	
	for (auto v : *(m_grid_u_v_inv_w_inv->m_voxels)) 
	{
		x = VoxelGrid::GetXFromKey(v.first);
		y = VoxelGrid::GetYFromKey(v.first);
		z = VoxelGrid::GetZFromKey(v.first);
		*r_addr_i = x; r_addr_i++;
		*r_addr_i = y; r_addr_i++;
		*r_addr_i = z; r_addr_i++;
		*r_addr_i = v.second.surface_points_count; r_addr_i++;
		*r_addr_i = v.second.edge_points_count; r_addr_i++;
		v.second.inOrigin ? *r_addr_i = 1 : *r_addr_i = 0; r_addr_i++;		
	}
	
	*r_addr_i = m_grid_u_inv_v_w->u_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w->v_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w->w_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w->points_total; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w->o_grid_u; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w->o_grid_v; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w->o_grid_w; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	*r_addr_f = m_grid_u_inv_v_w->grid_cell_spacing_u; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->grid_cell_spacing_v; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->grid_cell_spacing_w; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.U.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.U.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.U.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.V.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.V.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.V.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.W.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.W.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->uvw.W.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->o_model_xyz.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->o_model_xyz.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->o_model_xyz.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->max_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->max_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->max_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->max_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->max_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->max_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_model_uvw_br.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_model_uvw_br.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->min_model_uvw_br.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->scale.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->scale.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->scale.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w->rotation; r_addr_f++;					
	
	r_addr_i = (int*) r_addr_f;
	*r_addr_i = m_grid_u_inv_v_w->m_voxels->size(); r_addr_i++;	
	for (auto v : *(m_grid_u_inv_v_w->m_voxels)) 
	{
		x = VoxelGrid::GetXFromKey(v.first);
		y = VoxelGrid::GetYFromKey(v.first);
		z = VoxelGrid::GetZFromKey(v.first);
		*r_addr_i = x; r_addr_i++;
		*r_addr_i = y; r_addr_i++;
		*r_addr_i = z; r_addr_i++;
		*r_addr_i = v.second.surface_points_count; r_addr_i++;
		*r_addr_i = v.second.edge_points_count; r_addr_i++;
		v.second.inOrigin ? *r_addr_i = 1 : *r_addr_i = 0; r_addr_i++;		
	}
	
	*r_addr_i = m_grid_u_inv_v_inv_w->u_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w->v_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w->w_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w->points_total; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w->o_grid_u; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w->o_grid_v; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w->o_grid_w; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	*r_addr_f = m_grid_u_inv_v_inv_w->grid_cell_spacing_u; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->grid_cell_spacing_v; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->grid_cell_spacing_w; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.U.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.U.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.U.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.V.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.V.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.V.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.W.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.W.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->uvw.W.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->o_model_xyz.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->o_model_xyz.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->o_model_xyz.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->max_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->max_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->max_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->max_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->max_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->max_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_model_uvw_br.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_model_uvw_br.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->min_model_uvw_br.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->scale.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->scale.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->scale.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w->rotation; r_addr_f++;					
	
	r_addr_i = (int*) r_addr_f;
	
	*r_addr_i = m_grid_u_inv_v_inv_w->m_voxels->size(); r_addr_i++;	
	for (auto v : *(m_grid_u_inv_v_inv_w->m_voxels)) 
	{
		x = VoxelGrid::GetXFromKey(v.first);
		y = VoxelGrid::GetYFromKey(v.first);
		z = VoxelGrid::GetZFromKey(v.first);
		*r_addr_i = x; r_addr_i++;
		*r_addr_i = y; r_addr_i++;
		*r_addr_i = z; r_addr_i++;
		*r_addr_i = v.second.surface_points_count; r_addr_i++;
		*r_addr_i = v.second.edge_points_count; r_addr_i++;
		v.second.inOrigin ? *r_addr_i = 1 : *r_addr_i = 0; r_addr_i++;		
	}
		
	*r_addr_i = m_grid_u_inv_v_w_inv->u_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w_inv->v_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w_inv->w_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w_inv->points_total; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w_inv->o_grid_u; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w_inv->o_grid_v; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_w_inv->o_grid_w; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	*r_addr_f = m_grid_u_inv_v_w_inv->grid_cell_spacing_u; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->grid_cell_spacing_v; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->grid_cell_spacing_w; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.U.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.U.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.U.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.V.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.V.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.V.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.W.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.W.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->uvw.W.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->o_model_xyz.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->o_model_xyz.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->o_model_xyz.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->max_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->max_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->max_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->max_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->max_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->max_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_model_uvw_br.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_model_uvw_br.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->min_model_uvw_br.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->scale.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->scale.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->scale.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_w_inv->rotation; r_addr_f++;					
	
	r_addr_i = (int*) r_addr_f;
	*r_addr_i = m_grid_u_inv_v_w_inv->m_voxels->size(); r_addr_i++;	
	for (auto v : *(m_grid_u_inv_v_w_inv->m_voxels)) 
	{
		x = VoxelGrid::GetXFromKey(v.first);
		y = VoxelGrid::GetYFromKey(v.first);
		z = VoxelGrid::GetZFromKey(v.first);
		*r_addr_i = x; r_addr_i++;
		*r_addr_i = y; r_addr_i++;
		*r_addr_i = z; r_addr_i++;
		*r_addr_i = v.second.surface_points_count; r_addr_i++;
		*r_addr_i = v.second.edge_points_count; r_addr_i++;
		v.second.inOrigin ? *r_addr_i = 1 : *r_addr_i = 0; r_addr_i++;		
	}

	*r_addr_i = m_grid_u_inv_v_inv_w_inv->u_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w_inv->v_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w_inv->w_cells_count; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w_inv->points_total; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w_inv->o_grid_u; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w_inv->o_grid_v; r_addr_i++;
	*r_addr_i = m_grid_u_inv_v_inv_w_inv->o_grid_w; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->grid_cell_spacing_u; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->grid_cell_spacing_v; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->grid_cell_spacing_w; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.U.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.U.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.U.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.V.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.V.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.V.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.W.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.W.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->uvw.W.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->o_model_xyz.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->o_model_xyz.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->o_model_xyz.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->max_model_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->max_model_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->max_model_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->max_obb_uvw.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->max_obb_uvw.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->max_obb_uvw.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_model_uvw_br.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_model_uvw_br.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->min_model_uvw_br.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->scale.X; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->scale.Y; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->scale.Z; r_addr_f++;
	*r_addr_f = m_grid_u_inv_v_inv_w_inv->rotation; r_addr_f++;					
	
	r_addr_i = (int*) r_addr_f;	
	
	*r_addr_i = m_grid_u_inv_v_inv_w_inv->m_voxels->size(); r_addr_i++;	
	for (auto v : *(m_grid_u_inv_v_inv_w_inv->m_voxels)) 
	{
		x = VoxelGrid::GetXFromKey(v.first);
		y = VoxelGrid::GetYFromKey(v.first);
		z = VoxelGrid::GetZFromKey(v.first);
		*r_addr_i = x; r_addr_i++;
		*r_addr_i = y; r_addr_i++;
		*r_addr_i = z; r_addr_i++;
		*r_addr_i = v.second.surface_points_count; r_addr_i++;
		*r_addr_i = v.second.edge_points_count; r_addr_i++;
		v.second.inOrigin ? *r_addr_i = 1 : *r_addr_i = 0; r_addr_i++;		
	}	
		

	*r_addr_i = numberOfStringDescriptors; r_addr_i++;	
	for (auto sd : *m_stringDescriptors) 
	{
		*r_addr_i = sd.first; r_addr_i++;
		*r_addr_i = sd.second->size(); r_addr_i++;
		for (auto de : *(sd.second))
		{
			*r_addr_i = de.size(); r_addr_i++;
			for (auto dd : de) { *r_addr_i = dd; r_addr_i++; }
		}
	}
}

bool FeatureDescStructureGraph::ReadFromBFDSGFile(std::string _filepath)
{
	std::string pcsPath = _filepath+".bfdsg";		
	const char * filename = pcsPath.c_str();	
		
	boost::filesystem::path p (pcsPath, boost::filesystem::native);
	if ( !boost::filesystem::exists( p ) )
	{
		std::cerr << "Error : Couldn't open file '" << pcsPath << "'" << std::endl;
		return false;
	}
		
	//we assume all points/files fit in main memory
	boost::interprocess::file_mapping m_file;		
	boost::interprocess::mapped_region *m_region;
	
	m_file = boost::interprocess::file_mapping(filename, boost::interprocess::read_only);
	m_region = new boost::interprocess::mapped_region(m_file, boost::interprocess::read_only);					
	float * r_addr_f = (float*)m_region->get_address();
	int * r_addr_i = (int*)m_region->get_address();
	Int64 file_start = (Int64)r_addr_i;
	size_t r_size = m_region->get_size();						
	std::cout << "[BFDSGraph         ] Reading Bin File " << pcsPath << ". FileSize= [" << r_size << "]" << std::endl;
	
	int numberOfNodes = (int)*r_addr_i; r_addr_i++;	

	for (int i=0; i<numberOfNodes; i++) 
	{							
		Node *nNode = new FeatureDescStructureGraph::Node();
		nNode->id = (int)*r_addr_i; r_addr_i++;		
		nNode->used = (int)*r_addr_i; r_addr_i++;		
		r_addr_f = (float*) r_addr_i;
		nNode->coverage = (float) *r_addr_f; r_addr_f++;		
		nNode->distances_over_under.first = (float)*r_addr_f; r_addr_f++;
		nNode->distances_over_under.second = (float)*r_addr_f; 		
		r_addr_f++;
		
		r_addr_i = (int*) r_addr_f;
		nNode->point_count = (int)*r_addr_i; r_addr_i++;		
		nNode->shape = (SegmentsGraph::Shape)*r_addr_i; r_addr_i++;		
		r_addr_f = (float*) r_addr_i;
		nNode->orientation.X = (float)*r_addr_f; r_addr_f++;
		nNode->orientation.Y = (float)*r_addr_f; r_addr_f++;
		nNode->orientation.Z = (float)*r_addr_f; r_addr_f++;
		
		nNode->obb.obb_0.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.obb_0.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.obb_0.Z = (float)*r_addr_f; r_addr_f++;
		nNode->obb.obb_1.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.obb_1.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.obb_1.Z = (float)*r_addr_f; r_addr_f++;
		nNode->obb.obb_2.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.obb_2.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.obb_2.Z = (float)*r_addr_f; r_addr_f++;

		nNode->obb.p_0_min.Normal.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_0_min.Normal.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_0_min.Normal.Z = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_0_min.Distance = (float)*r_addr_f; r_addr_f++;

		nNode->obb.p_0_max.Normal.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_0_max.Normal.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_0_max.Normal.Z = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_0_max.Distance = (float)*r_addr_f; r_addr_f++;
		
		nNode->obb.p_1_min.Normal.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_1_min.Normal.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_1_min.Normal.Z = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_1_min.Distance = (float)*r_addr_f; r_addr_f++;

		nNode->obb.p_1_max.Normal.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_1_max.Normal.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_1_max.Normal.Z = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_1_max.Distance = (float)*r_addr_f; r_addr_f++;

		nNode->obb.p_2_min.Normal.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_2_min.Normal.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_2_min.Normal.Z = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_2_min.Distance = (float)*r_addr_f; r_addr_f++;

		nNode->obb.p_2_max.Normal.X = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_2_max.Normal.Y = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_2_max.Normal.Z = (float)*r_addr_f; r_addr_f++;
		nNode->obb.p_2_max.Distance = (float)*r_addr_f; r_addr_f++;

		nNode->obb.buffer = (float)*r_addr_f; r_addr_f++;			
		r_addr_i = (int*) r_addr_f;
		int numberOfEdges = (int)*r_addr_i; r_addr_i++;
			
		for (int j=0; j<numberOfEdges; j++)
		{		
			int sinkNode = (int)*r_addr_i; r_addr_i++;
			r_addr_f = (float*) r_addr_i;
			EdgeStats * es = new EdgeStats();
			es->strength = (float)*r_addr_f; r_addr_f++;
			es->epsilon = (float)*r_addr_f; r_addr_f++;
			es->direct = (float)*r_addr_f; r_addr_f++;
			es->occluded = (float)*r_addr_f; r_addr_f++;
			r_addr_i = (int*) r_addr_f;
			int discon = (int)*r_addr_i; r_addr_i++;
			if (discon == 0) es->disconnected = false; else es->disconnected = true;
			int numberOfActions = (int)*r_addr_i; r_addr_i++;
			for (int k=0; k<numberOfActions; k++) { es->actions.push_back((action)*r_addr_i); r_addr_i++; }
			(*(nNode->edges))[sinkNode] = es;											
		}			

		(*nodes)[nNode->id] = nNode;
	} //all nodes should be read now

	//Start reading grids now.

	int numberOfGrids = (int)*r_addr_i; r_addr_i++;	

	m_grid_u_v_w = new VoxelGrid(1,1,1);
	m_grid_u_v_w->u_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w->v_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w->w_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w->points_total=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w->o_grid_u=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w->o_grid_v=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w->o_grid_w=(int)*r_addr_i; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	m_grid_u_v_w->grid_cell_spacing_u=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->grid_cell_spacing_v=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->grid_cell_spacing_w=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.U.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.U.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.U.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.V.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.V.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.V.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.W.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.W.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->uvw.W.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->o_model_xyz.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->o_model_xyz.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->o_model_xyz.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->max_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->max_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->max_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->max_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->max_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->max_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_model_uvw_br.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_model_uvw_br.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->min_model_uvw_br.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->scale.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->scale.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->scale.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w->rotation=(float)*r_addr_f; r_addr_f++;	
	m_grid_u_v_w->m_parent = this;
	
	r_addr_i = (int*) r_addr_f;	
	int numberOfVoxels = (int)*r_addr_i; r_addr_i++;
	int x,y,z, key, inOrigin;
	for (int i=0; i<numberOfVoxels; i++) 
	{
		x = (int)*r_addr_i; r_addr_i++;
		y = (int)*r_addr_i; r_addr_i++;
		z = (int)*r_addr_i; r_addr_i++;		
		key = VoxelGrid::GetKey(x, y, z);
		VoxelGrid::VoxelGridCell cell;
		cell.u_pos = x;
		cell.v_pos = y; 
		cell.w_pos = z;
		cell.surface_points_count = (int)*r_addr_i; r_addr_i++;
		cell.edge_points_count = (int)*r_addr_i; r_addr_i++;
		inOrigin = (int)*r_addr_i; r_addr_i++;
		if (inOrigin==0) cell.inOrigin = false; else cell.inOrigin = true;
		(*(m_grid_u_v_w->m_voxels))[key] = cell;		
	}

	m_grid_u_v_inv_w = new VoxelGrid(1,1,1);
	m_grid_u_v_inv_w->u_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w->v_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w->w_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w->points_total=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w->o_grid_u=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w->o_grid_v=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w->o_grid_w=(int)*r_addr_i; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	m_grid_u_v_inv_w->grid_cell_spacing_u=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->grid_cell_spacing_v=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->grid_cell_spacing_w=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.U.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.U.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.U.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.V.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.V.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.V.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.W.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.W.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->uvw.W.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->o_model_xyz.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->o_model_xyz.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->o_model_xyz.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->max_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->max_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->max_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->max_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->max_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->max_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_model_uvw_br.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_model_uvw_br.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->min_model_uvw_br.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->scale.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->scale.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->scale.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w->rotation=(float)*r_addr_f; r_addr_f++;			
	m_grid_u_v_inv_w->m_parent = this;

	r_addr_i = (int*) r_addr_f;	
	numberOfVoxels = (int)*r_addr_i; r_addr_i++;
	for (int i=0; i<numberOfVoxels; i++) 
	{
		x = (int)*r_addr_i; r_addr_i++;
		y = (int)*r_addr_i; r_addr_i++;
		z = (int)*r_addr_i; r_addr_i++;		
		key = VoxelGrid::GetKey(x, y, z);
		VoxelGrid::VoxelGridCell cell;
		cell.surface_points_count = (int)*r_addr_i; r_addr_i++;
		cell.edge_points_count = (int)*r_addr_i; r_addr_i++;
		inOrigin = (int)*r_addr_i; r_addr_i++;
		if (inOrigin==0) cell.inOrigin = false; else cell.inOrigin = true;
		(*(m_grid_u_v_inv_w->m_voxels))[key] = cell;		
	}


	m_grid_u_v_w_inv = new VoxelGrid(1,1,1);
	m_grid_u_v_w_inv->u_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w_inv->v_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w_inv->w_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w_inv->points_total=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w_inv->o_grid_u=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w_inv->o_grid_v=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_w_inv->o_grid_w=(int)*r_addr_i; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	m_grid_u_v_w_inv->grid_cell_spacing_u=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->grid_cell_spacing_v=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->grid_cell_spacing_w=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.U.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.U.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.U.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.V.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.V.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.V.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.W.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.W.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->uvw.W.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->o_model_xyz.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->o_model_xyz.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->o_model_xyz.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->max_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->max_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->max_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->max_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->max_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->max_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_model_uvw_br.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_model_uvw_br.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->min_model_uvw_br.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->scale.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->scale.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->scale.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_w_inv->rotation=(float)*r_addr_f; r_addr_f++;	
	m_grid_u_v_w_inv->m_parent = this;
	
	r_addr_i = (int*) r_addr_f;	

	numberOfVoxels = (int)*r_addr_i; r_addr_i++;	
	for (int i=0; i<numberOfVoxels; i++) 
	{
		x = (int)*r_addr_i; r_addr_i++;
		y = (int)*r_addr_i; r_addr_i++;
		z = (int)*r_addr_i; r_addr_i++;		
		key = VoxelGrid::GetKey(x, y, z);
		VoxelGrid::VoxelGridCell cell;
		cell.surface_points_count = (int)*r_addr_i; r_addr_i++;
		cell.edge_points_count = (int)*r_addr_i; r_addr_i++;
		inOrigin = (int)*r_addr_i; r_addr_i++;
		if (inOrigin==0) cell.inOrigin = false; else cell.inOrigin = true;
		(*(m_grid_u_v_w_inv->m_voxels))[key] = cell;		
	}
	
	m_grid_u_v_inv_w_inv = new VoxelGrid(1,1,1);
	m_grid_u_v_inv_w_inv->u_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w_inv->v_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w_inv->w_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w_inv->points_total=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w_inv->o_grid_u=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w_inv->o_grid_v=(int)*r_addr_i; r_addr_i++;
	m_grid_u_v_inv_w_inv->o_grid_w=(int)*r_addr_i; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	m_grid_u_v_inv_w_inv->grid_cell_spacing_u=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->grid_cell_spacing_v=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->grid_cell_spacing_w=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.U.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.U.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.U.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.V.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.V.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.V.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.W.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.W.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->uvw.W.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->o_model_xyz.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->o_model_xyz.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->o_model_xyz.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->max_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->max_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->max_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->max_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->max_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->max_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_model_uvw_br.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_model_uvw_br.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->min_model_uvw_br.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->scale.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->scale.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->scale.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_v_inv_w_inv->rotation=(float)*r_addr_f; r_addr_f++;	
	m_grid_u_v_inv_w_inv->m_parent = this;

	r_addr_i = (int*) r_addr_f;	
	numberOfVoxels = (int)*r_addr_i; r_addr_i++;
	for (int i=0; i<numberOfVoxels; i++) 
	{
		x = (int)*r_addr_i; r_addr_i++;
		y = (int)*r_addr_i; r_addr_i++;
		z = (int)*r_addr_i; r_addr_i++;		
		key = VoxelGrid::GetKey(x, y, z);
		VoxelGrid::VoxelGridCell cell;
		cell.surface_points_count = (int)*r_addr_i; r_addr_i++;
		cell.edge_points_count = (int)*r_addr_i; r_addr_i++;
		inOrigin = (int)*r_addr_i; r_addr_i++;
		if (inOrigin==0) cell.inOrigin = false; else cell.inOrigin = true;
		(*(m_grid_u_v_inv_w_inv->m_voxels))[key] = cell;		
	}
	
	m_grid_u_inv_v_w = new VoxelGrid(1,1,1);
	m_grid_u_inv_v_w->u_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w->v_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w->w_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w->points_total=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w->o_grid_u=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w->o_grid_v=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w->o_grid_w=(int)*r_addr_i; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	m_grid_u_inv_v_w->grid_cell_spacing_u=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->grid_cell_spacing_v=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->grid_cell_spacing_w=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.U.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.U.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.U.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.V.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.V.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.V.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.W.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.W.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->uvw.W.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->o_model_xyz.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->o_model_xyz.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->o_model_xyz.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->max_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->max_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->max_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->max_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->max_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->max_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_model_uvw_br.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_model_uvw_br.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->min_model_uvw_br.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->scale.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->scale.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->scale.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w->rotation=(float)*r_addr_f; r_addr_f++;	
	m_grid_u_inv_v_w->m_parent = this;

	r_addr_i = (int*) r_addr_f;	

	numberOfVoxels = (int)*r_addr_i; r_addr_i++;
	for (int i=0; i<numberOfVoxels; i++) 
	{
		x = (int)*r_addr_i; r_addr_i++;
		y = (int)*r_addr_i; r_addr_i++;
		z = (int)*r_addr_i; r_addr_i++;		
		key = VoxelGrid::GetKey(x, y, z);
		VoxelGrid::VoxelGridCell cell;
		cell.surface_points_count = (int)*r_addr_i; r_addr_i++;
		cell.edge_points_count = (int)*r_addr_i; r_addr_i++;
		inOrigin = (int)*r_addr_i; r_addr_i++;
		if (inOrigin==0) cell.inOrigin = false; else cell.inOrigin = true;
		(*(m_grid_u_inv_v_w->m_voxels))[key] = cell;		
	}
	
	m_grid_u_inv_v_inv_w = new VoxelGrid(1,1,1);
	m_grid_u_inv_v_inv_w->u_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w->v_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w->w_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w->points_total=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w->o_grid_u=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w->o_grid_v=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w->o_grid_w=(int)*r_addr_i; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	m_grid_u_inv_v_inv_w->grid_cell_spacing_u=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->grid_cell_spacing_v=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->grid_cell_spacing_w=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.U.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.U.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.U.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.V.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.V.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.V.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.W.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.W.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->uvw.W.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->o_model_xyz.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->o_model_xyz.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->o_model_xyz.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->max_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->max_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->max_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->max_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->max_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->max_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_model_uvw_br.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_model_uvw_br.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->min_model_uvw_br.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->scale.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->scale.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->scale.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w->rotation=(float)*r_addr_f; r_addr_f++;	
	m_grid_u_inv_v_inv_w->m_parent = this;

	r_addr_i = (int*) r_addr_f;	

	numberOfVoxels = (int)*r_addr_i; r_addr_i++;
	for (int i=0; i<numberOfVoxels; i++) 
	{
		x = (int)*r_addr_i; r_addr_i++;
		y = (int)*r_addr_i; r_addr_i++;
		z = (int)*r_addr_i; r_addr_i++;		
		key = VoxelGrid::GetKey(x, y, z);
		VoxelGrid::VoxelGridCell cell;
		cell.surface_points_count = (int)*r_addr_i; r_addr_i++;
		cell.edge_points_count = (int)*r_addr_i; r_addr_i++;
		inOrigin = (int)*r_addr_i; r_addr_i++;
		if (inOrigin==0) cell.inOrigin = false; else cell.inOrigin = true;
		(*(m_grid_u_inv_v_inv_w->m_voxels))[key] = cell;		
	}
	
	m_grid_u_inv_v_w_inv = new VoxelGrid(1,1,1);
	m_grid_u_inv_v_w_inv->u_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w_inv->v_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w_inv->w_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w_inv->points_total=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w_inv->o_grid_u=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w_inv->o_grid_v=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_w_inv->o_grid_w=(int)*r_addr_i; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	m_grid_u_inv_v_w_inv->grid_cell_spacing_u=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->grid_cell_spacing_v=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->grid_cell_spacing_w=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.U.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.U.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.U.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.V.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.V.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.V.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.W.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.W.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->uvw.W.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->o_model_xyz.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->o_model_xyz.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->o_model_xyz.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->max_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->max_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->max_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->max_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->max_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->max_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_model_uvw_br.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_model_uvw_br.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->min_model_uvw_br.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->scale.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->scale.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->scale.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_w_inv->rotation=(float)*r_addr_f; r_addr_f++;	
	m_grid_u_inv_v_w_inv->m_parent = this;

	r_addr_i = (int*) r_addr_f;	

	numberOfVoxels = (int)*r_addr_i; r_addr_i++;
	for (int i=0; i<numberOfVoxels; i++) 
	{
		x = (int)*r_addr_i; r_addr_i++;
		y = (int)*r_addr_i; r_addr_i++;
		z = (int)*r_addr_i; r_addr_i++;		
		key = VoxelGrid::GetKey(x, y, z);
		VoxelGrid::VoxelGridCell cell;
		cell.surface_points_count = (int)*r_addr_i; r_addr_i++;
		cell.edge_points_count = (int)*r_addr_i; r_addr_i++;
		inOrigin = (int)*r_addr_i; r_addr_i++;
		if (inOrigin==0) cell.inOrigin = false; else cell.inOrigin = true;
		(*(m_grid_u_inv_v_w_inv->m_voxels))[key] = cell;		
	}

	m_grid_u_inv_v_inv_w_inv = new VoxelGrid(1,1,1);
	m_grid_u_inv_v_inv_w_inv->u_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w_inv->v_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w_inv->w_cells_count=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w_inv->points_total=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w_inv->o_grid_u=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w_inv->o_grid_v=(int)*r_addr_i; r_addr_i++;
	m_grid_u_inv_v_inv_w_inv->o_grid_w=(int)*r_addr_i; r_addr_i++;
	r_addr_f = (float*) r_addr_i;	
	m_grid_u_inv_v_inv_w_inv->grid_cell_spacing_u=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->grid_cell_spacing_v=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->grid_cell_spacing_w=(float)*r_addr_f; r_addr_f++;	
	m_grid_u_inv_v_inv_w_inv->uvw.U.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->uvw.U.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->uvw.U.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->uvw.V.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->uvw.V.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->uvw.V.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->uvw.W.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->uvw.W.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->uvw.W.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->o_model_xyz.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->o_model_xyz.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->o_model_xyz.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->max_model_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->max_model_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->max_model_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->max_obb_uvw.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->max_obb_uvw.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->max_obb_uvw.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_model_uvw_br.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_model_uvw_br.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->min_model_uvw_br.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->scale.X=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->scale.Y=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->scale.Z=(float)*r_addr_f; r_addr_f++;
	m_grid_u_inv_v_inv_w_inv->rotation=(float)*r_addr_f; r_addr_f++;	
	m_grid_u_inv_v_inv_w_inv->m_parent = this;

	r_addr_i = (int*) r_addr_f;	

	numberOfVoxels = (int)*r_addr_i; r_addr_i++;
	for (int i=0; i<numberOfVoxels; i++) 
	{
		x = (int)*r_addr_i; r_addr_i++;
		y = (int)*r_addr_i; r_addr_i++;
		z = (int)*r_addr_i; r_addr_i++;		
		key = VoxelGrid::GetKey(x, y, z);
		VoxelGrid::VoxelGridCell cell;
		cell.surface_points_count = (int)*r_addr_i; r_addr_i++;
		cell.edge_points_count = (int)*r_addr_i; r_addr_i++;
		inOrigin = (int)*r_addr_i; r_addr_i++;
		if (inOrigin==0) cell.inOrigin = false; else cell.inOrigin = true;
		(*(m_grid_u_inv_v_inv_w_inv->m_voxels))[key] = cell;		
	}	

	//Get String Descriptors now.
	int numberOfStringDescriptors = (int)*r_addr_i; r_addr_i++;	
	for (int i=0; i<numberOfStringDescriptors; i++) 
	{
		int length = (int)*r_addr_i; r_addr_i++;
		int numberOfDesc = (int)*r_addr_i; r_addr_i++;
		std::vector<std::vector<int>> *descWithSizeN = new std::vector<std::vector<int>>(); 
		for (int j=0; j<numberOfDesc; j++)
		{
			std::vector<int> desc;
			int lengthOfDesc = (int)*r_addr_i; r_addr_i++;
			for (int k=0; k<lengthOfDesc; k++) { desc.push_back((int)*r_addr_i); r_addr_i++; }
			descWithSizeN->push_back(desc);
		}
		(*m_stringDescriptors)[length] = descWithSizeN;
	}

	return true;
}
			
void FeatureDescStructureGraph::PrintDescriptors()
{
	std::stringstream mess;
	for (std::map<int, std::vector<std::vector<int>>*>::iterator desc_map_it = m_stringDescriptors->begin(); desc_map_it != m_stringDescriptors->end(); desc_map_it++)
	{		
		mess.str(std::string("")); mess << "Descriptors of Length " << desc_map_it->first << " Count=" << desc_map_it->second->size();
		(*(m_pcs->m_pEnvironment->GetLogger()))["Training"]->Write(mess.str(), LL_Critical);
		mess.str(std::string(""));
		for (std::vector<std::vector<int>>::iterator desc_length_it = desc_map_it->second->begin(); desc_length_it != desc_map_it->second->end(); desc_length_it++)
		{
			mess.str(std::string("-> "));
			for (std::vector<int>::iterator desc_it = desc_length_it->begin(); desc_it != desc_length_it->end(); desc_it++) 
			{
				mess << *desc_it << " ";
			}
			(*(m_pcs->m_pEnvironment->GetLogger()))["Training"]->Write(mess.str(), LL_Info);
			mess.str(std::string(""));
		}
	}
}
